<template>
  <q-page class="q-pa-md">
    <div class="q-pb-md text-h5">{{pageTitle}} <span class="text-subtitle1">{{pageSubTitle}}</span></div>
    <div class="q-pa-sm shadow-2 q-mb-md">
      <div class="btn q-gutter-sm">
        <q-btn @click="detailNav.goBackToList" color="primary" icon="arrow_back" outline :title="$t('返回')" no-caps />
        <q-btn @click="loadModelData" color="primary" dense icon="refresh" outline :title="$t('刷新')" no-caps :disable="loadingState"
          :loading="loadingState" v-if="isViewOrEditMode" />
        <q-btn @click="detailNav.goEditMode" color="primary" icon="edit" :label="$t('编辑')" no-caps
          v-if="fx.hasModifyRight('Comm.UserMgr.Edit') && isViewMode && ($d.form.userName && $d.form.userName.toLowerCase() !== 'admin')"
          :disable="loadingState" />
        <q-btn @click="deleteUser" color="red" icon="delete_outline" :label="$t('删除')" no-caps
          v-if="fx.hasModifyRight('Comm.UserMgr.Edit') && isViewMode && ($d.form.userName && $d.form.userName.toLowerCase() !== 'admin')"
          :disable="loadingState" />
        <q-btn @click="showChangePwdByAdminDialog" color="primary" icon="vpn_key" :label="$t('修改密码')" no-caps
          v-if="fx.hasModifyRight('Comm.UserMgr.Edit') && isViewMode && fx.ua.value.userName.toLowerCase() === 'admin' && props.allowResetPasswordByAdmin === true"
          :disable="loadingState || submittingState" />
        <q-btn @click="doSubmit" color="primary" :loading="submittingState" :label="$t('确定')" no-caps
          v-if="isCreateOrEditMode" :disable="loadingState" />
        <q-btn @click="detailNav.cancelSubmit" color="primary" outline :label="$t('取消')" no-caps v-if="isEditMode"
          :disable="submittingState" />
      </div>
    </div>
    <!--错误提示-->
    <q-banner class="text-white bg-red q-mt-md" dense inline-actions v-if="serverErrorMessage">
      {{serverErrorMessage}}
      <template v-slot:action>
        <q-btn flat icon="close" size="sm" dense @click="serverErrorMessage=null" />
      </template>
    </q-banner>
    <!--折叠栏开始-->
    <!-- form -->
    <form-field-group title="主要信息" no-caps :model-with-create-update="$d.form">
      <div class="q-pa-sm">
        <div class="row q-col-gutter-sm col-12 q-mb-sm">
          <div class="col-12 col-sm-6 col-md-4 col-lg-3">
            <q-icon color="red" name="fas fa-asterisk" size="10px" />
            <span>{{$t('用户名')}}</span>
            <q-input :error="v$.userName.$error" :error-message="e$(v$.userName.$errors)" :hide-bottom-space="true"
              :readonly="isViewOrEditMode" dense :maxlength="30" no-error-icon outlined square stack-label
              v-model="$d.form.userName" autofocus></q-input>
          </div>
          <div class="col-12 col-sm-6 col-md-4 col-lg-3">
            <span>{{$t('有效')}}</span>
            <div class="bg-grey-3">
              <q-checkbox dense :disable="isViewMode" class="full-width q-pa-xs" color="primary"
                v-model="$d.form.enabledState" />
            </div>
          </div>
          <div class="col-12 col-sm-6 col-md-4 col-lg-3">
            <span>{{$t('API账号')}}</span>
            <q-icon name="fas fa-info" class="q-mb-xs" color="info">
              <q-tooltip transition-show="none" transition-hide="none" anchor="center right" self="center left">
                {{$t('勾选中表明这是一个API专用账号，不能用此账号登录使用系统前端页面')}}
              </q-tooltip>
            </q-icon>
            <div class="bg-grey-3">
              <q-checkbox dense :disable="isViewMode" class="full-width q-pa-xs" color="primary"
                v-model="$d.form.isApiUser" />
            </div>
          </div>

          <div class="col-12 col-sm-6 col-md-4 col-lg-3">
            <span>{{$t('外部系统账号')}}</span>
            <q-icon name="fas fa-info" class="q-mb-xs" color="info">
              <q-tooltip transition-show="none" transition-hide="none" anchor="center right" self="center left">
                {{$t('如果系统需要和外部系统进行对接，请在此处填入外部系统与此用户对应的账号')}}
              </q-tooltip>
            </q-icon>
            <q-input :hide-bottom-space="true" :readonly="isViewMode" dense :maxlength="30" no-error-icon outlined
              square stack-label v-model="$d.form.externalUserName"></q-input>
          </div>

        </div>
        <div class="row q-col-gutter-sm col-12 q-mb-sm">
          <div class="col-12 col-sm-6 col-md-4 col-lg-3">
            <q-icon color="red" name="fas fa-asterisk" size="10px" />
            <span>{{$t('真实姓名')}}</span>
            <q-input :error="v$.realName.$error" :error-message="e$(v$.realName.$errors)" :hide-bottom-space="true"
              :readonly="isViewMode" dense :maxlength="30" no-error-icon outlined square stack-label
              v-model="$d.form.realName"></q-input>
          </div>
          <div class="col-12 col-sm-6 col-md-4 col-lg-3">
            <q-icon color="red" name="fas fa-asterisk" size="10px" />
            <span>email</span>
            <q-input :error="v$.email.$error" :error-message="e$(v$.email.$errors)" :hide-bottom-space="true"
              :readonly="isViewMode" dense :maxlength="30" no-error-icon outlined square stack-label
              v-model="$d.form.email"></q-input>
          </div>
          <div class="col-12 col-sm-6 col-md-4 col-lg-3">
            <span>{{$t('手机号码')}}</span>
            <q-input :error="v$.mobilePhone.$error" :error-message="e$(v$.mobilePhone.$errors)"
              :hide-bottom-space="true"
              :readonly="isViewMode" dense :maxlength="30" no-error-icon outlined square stack-label
              v-model="$d.form.mobilePhone"></q-input>
          </div>
        </div>
        <div class="row q-col-gutter-sm col-12 q-mb-sm">
          <div class="col-12 col-sm-12 col-md-8 col-lg-6"
            v-if="fx.hasRight('Comm.RoleRight.UserRoleAssign')||isViewMode">
            <span>{{$t('角色')}}</span>
            <q-select :readonly="isViewMode" :options="$d.roleOption" clearable dense emit-value filled
              map-options multiple options-dense placeholder="多选" square stack-label transition-hide="none"
              transition-show="none" v-model="$d.form.userRoleIds"></q-select>
          </div>
          <div class="col-12 col-sm-6 col-md-4 col-lg-3" v-if="props.internalTagsType>0">
            <q-icon v-if="props.internalTagsMandatory" color="red" name="fas fa-asterisk" size="10px" />
            <span>{{props.internalTagsLabel}}</span>
            <simple-filter-select :error="v$.internalTags.$error" :error-message="e$(v$.internalTags.$errors)"
              option-label="label" :readonly="isViewMode" :options="props.internalTagsData" option-value="value"
              v-model="$d.form.internalTags" :use-filter="false" />
          </div>
        </div>
      </div>
    </form-field-group>
    <!--修改密码对话框 persistent 禁止点击空白区域关闭窗口-->
    <q-dialog persistent transition-hide="none" transition-show="none" v-model="changePwdByAdminDialogState">
      <q-card style="width: 320px">
        <q-card-section class="q-pa-sm">
          <div class="text-h6">{{$t('修改密码')}}</div>
        </q-card-section>
        <q-separator />
        <q-banner class="text-white bg-red q-mx-sm q-mt-sm" dense inline-actions v-if="changePwdServerErrorMessage">
          {{changePwdServerErrorMessage}}
        </q-banner>
        <q-card-section class="scroll q-pa-sm">
          <div class="q-pb-md">
            <q-icon color="red" name="fas fa-asterisk" size="10px" />
            <span>{{$t('密码')}}</span>
            <q-input :error="vChgPwd$.newPassword.$error" :error-message="e$(vChgPwd$.newPassword.$errors)"
              :hide-bottom-space="true" dense autofocus
              :maxlength="30" no-error-icon outlined ref="val1" square stack-label type="password"
              v-model="$d.formChgPwd.newPassword">
            </q-input>
          </div>
          <div class="q-pb-md">
            <q-icon color="red" name="fas fa-asterisk" size="10px" />
            <span>{{$t('再次输入密码')}}</span>
            <q-input :error="vChgPwd$.confirmPassword.$error" :error-message="e$(vChgPwd$.confirmPassword.$errors)"
              :hide-bottom-space="true" dense
              :maxlength="30" no-error-icon outlined ref="val2" square stack-label type="password"
              v-model="$d.formChgPwd.confirmPassword">
            </q-input>
          </div>
        </q-card-section>

        <q-separator />

        <q-card-actions align="right">
          <q-btn @click="changePasswordByAdmin" color="primary" :label="$t('确定')" no-caps unelevated
            :loading="changePwdByAdminSubmittingState" :disable="changePwdByAdminSubmittingState" />
          <q-btn color="primary" :label="$t('取消')" no-caps outline unelevated v-close-popup
            :disable="changePwdByAdminSubmittingState" />
        </q-card-actions>
      </q-card>
    </q-dialog>
  </q-page>
</template>

<script lang="ts">
export default {
  name: 'userStd',
}
</script>

<script lang="ts" setup>
import {useTitleHelper} from '../../hooks/titleHelper'
import {useDetailHelper} from '../../hooks/detailHelper'
import {computed, reactive, ref} from 'vue'
import {UserInfo} from '../../defs/user'
import {Role} from '../../defs/role'
import useVuelidate from '@vuelidate/core'
import {AxiosResponse} from 'axios'
import {GenericDropdownListItem} from '../../defs/comm'
import FormFieldGroup from '../../components/FormFieldGroup.vue'
import {useJsencryptHelper} from '../../hooks/jsencryptHelper'
import { useI18n } from 'vue-i18n'
const {t} = useI18n()

interface PropsDef {
  //是否使用严格密码
  useStrictPassword?: boolean

  //内部标志类型：0-不显示 1-单选下拉
  internalTagsType?: number
  //内部标志的下拉数据
  internalTagsData?: GenericDropdownListItem[]
  //内部标志是否必填
  internalTagsMandatory?: boolean
  //内部标志位栏位的标签
  internalTagsLabel?: string,
  //是否允许管理员重置密码
  allowResetPasswordByAdmin:boolean
}

const props = withDefaults(defineProps<PropsDef>(), {
  useStrictPassword: false,
  internalTagsType: 0,
  internalTagsData: () => [],
  internalTagsMandatory: false,
  internalTagsLabel: '内部标志位',
  allowResetPasswordByAdmin:true
})

const pageTitle = t('用户管理')
useTitleHelper(pageTitle)

const encPassword = useJsencryptHelper()

// 新建时候的默认值
const defFormDataForCreate = {
  enabledState: true,
  isApiUser: false,
}

const serverErrorMessage = ref('')

const $d = reactive({
  // 表单数据
  form: {} as UserInfo,
  // 角色下拉数据源
  roleOption: [] as GenericDropdownListItem[],
  // 修改密码表单
  formChgPwd: {
    // 密码修改相关
    // 新密码
    newPassword: '',
    // 确认新密码
    confirmPassword: '',
  },
})

const validators = $f.validators

//主表单验证
const rules = {
  userName: {
    required: validators.required,
    username: validators.username,
  },
  realName: {
    required: validators.required,
    realName: validators.realName,
  },
  email: {
    required: validators.required,
    email: validators.email,
  },
  mobilePhone: {
    phone: validators.phone,
  },
  internalTags: {
    required: validators.requiredIf(computed(() => props.internalTagsMandatory)),
  },
}

const v$ = useVuelidate(rules, computed(() => $d.form), {$autoDirty: true})

//修改密码表单验证
const rulesChgPwd = {
  newPassword: {
    required: validators.required,
    password: props.useStrictPassword ? validators.strictPassword : validators.password,
  },
  confirmPassword: {
    required: validators.required,
    password: props.useStrictPassword ? validators.strictPassword : validators.password,
    passwordConfirm: validators.passwordConfirm(computed(() => $d.formChgPwd.newPassword)),
  },
}

const vChgPwd$ = useVuelidate(rulesChgPwd, $d.formChgPwd, {$autoDirty: true})

// 修改密码弹框的错误信息
const changePwdServerErrorMessage = ref('')
// 修改密码弹框状态
const changePwdByAdminDialogState = ref(false)

// 弹出修改密码框
const showChangePwdByAdminDialog = function () {
  $d.formChgPwd.newPassword = ''
  $d.formChgPwd.confirmPassword = ''
  changePwdServerErrorMessage.value = ''
  changePwdByAdminDialogState.value = true
  vChgPwd$.value.$reset()
}

const loadingState = ref(false)
// 加载数据
const loadModelData = function () {
  serverErrorMessage.value = ''
  loadingState.value = true
  $f.axios
    .get<UserInfo>('/comm/usermgr/get-user-info/' + decodeURIComponent(detailInfo.itemId))
    .then((result) => {
      $d.form = result.data
      $f.misc.simpleAssign($d.form, result.data)
    })
    .catch((err) => {
      $f.ui.showNotifyFailed($f.getAxiosErrMsg(err))
    })
    .finally(() => {
      loadingState.value = false
    })
}

const {
  detailInfo,
  detailStatus,
  detailNav,
} = useDetailHelper('/comm/cfg/user',
  $d.form,
  defFormDataForCreate,
  '/comm/cfg/user',
  '/comm/cfg/user/detail',
  '/comm/cfg/user/create',
  '/comm/cfg/user/edit',
  loadModelData,
  serverErrorMessage,
)

//
const {
  isViewMode,
  isCreateMode,
  isEditMode,
  isCreateOrEditMode,
  isViewOrEditMode,
  pageSubTitle,
} = detailStatus

// 数据加载/提交状态
const submittingState = ref(false)

// 修改/新增提交
const doSubmit = () => {
  serverErrorMessage.value = ''
  void v$.value
    .$validate()
    .then((valRes) => {
      if (valRes) {
        if (isCreateMode.value) {
          submittingState.value = true
          $f.axios
            .post('/comm/usermgr/add-user', $d.form)
            .then((): Promise<void | AxiosResponse<void>> => {
              if ($f.hasRight('Comm.RoleRight.UserRoleAssign')) {
                let params = {
                  userName: $d.form.userName,
                  roleIds: $d.form.userRoleIds,
                }
                return $f.axios.post('/comm/rr/set-user-role', params)
              } else {
                return Promise.resolve()
              }
            })
            .then(() => {
              detailNav.goBackToList()
            })
            .catch((err) => {
              serverErrorMessage.value = $f.getAxiosErrMsg(err)
            })
            .finally(() => {
              submittingState.value = false
            })
        } else if (isEditMode.value) {
          submittingState.value = true
          $f.axios.post('/comm/usermgr/edit-user', $d.form)
            .then((): Promise<void | AxiosResponse<void>> => {
              if ($f.hasRight('Comm.RoleRight.UserRoleAssign')) {
                let params = {
                  userName: $d.form.userName,
                  roleIds: $d.form.userRoleIds,
                }
                return $f.axios.post('/comm/rr/set-user-role', params)
              } else {
                return Promise.resolve()
              }
            })
            .then(() => {
              detailNav.doneEdit()
            })
            .catch((err) => {
              serverErrorMessage.value = $f.getAxiosErrMsg(err)
            })
            .finally(() => {
              submittingState.value = false
            })
        }
      }
    })
}

const changePwdByAdminSubmittingState = ref(false)

// 删除用户
const deleteUser = function () {
  void $f.ui.messageBox({
    caption: t('操作确认'),
    text: t('确定要删除该用户吗'),
    icon: 'Warning',
    buttons: 'OkCancel',
    delayClose: true,
  }).then((btn) => {
    if (btn === 'ok') {
      $f.axios
        .post('/comm/usermgr/delete-user/' + decodeURIComponent(detailInfo.itemId))
        .then(() => {
          $f.ui.closeMsgBox()
          detailNav.goBackToList()
        })
        .catch((err) => {
          void $f.ui.messageBox({
            caption: t('删除失败'),
            text: $f.getAxiosErrMsg(err),
            icon: $f.getAxiosErrIcon(err),
            buttons: 'Close',
          })
        })
    }
  })
}

// 确定修改密码
const changePasswordByAdmin = function () {
  changePwdServerErrorMessage.value = ''
  void vChgPwd$.value
    .$validate()
    .then((valRes) => {
      if (valRes) {
        changePwdByAdminSubmittingState.value = true
        let changePasswordModel
        if ($f.globalCfg.encTransPwd) {
          changePasswordModel = {
            username: decodeURIComponent(detailInfo.itemId),
            useEncryptPwd: true,
            encryptedNewPwd: encPassword($d.formChgPwd.newPassword),
          }
        } else {
          changePasswordModel = {
            username: decodeURIComponent(detailInfo.itemId),
            newPassword: $d.formChgPwd.newPassword,
          }
        }

        $f.axios
          .post('/comm/auth/change-password-by-admin', changePasswordModel)
          .then(() => {
            changePwdByAdminDialogState.value = false
            loadModelData()
          })
          .catch((err) => {
            changePwdServerErrorMessage.value = $f.getAxiosErrMsg(err)
          })
          .finally(() => {
            changePwdByAdminSubmittingState.value = false
          })
      }
    })
}

// region 初始化动作

//获取角色
$f.axios
  .get<Role[]>('/comm/rr/get-all-roles')
  .then((result) => {
    for (let i of result.data) {
      $d.roleOption.push({
        label: i.roleName,
        value: i.roleId,
      })
    }
  })
  .catch((err) => {
    changePwdServerErrorMessage.value = $f.getAxiosErrMsg(err)
  })

const fx = $f
const e$ = $f.getFieldErrStr
// endregion

</script>
